package com.sm2cppa.controller;

import com.sm2cppa.contract.MapPkToTx;

import com.sm2cppa.entity.CertBody;
import com.sm2cppa.entity.ResponseBody;
import com.sm2cppa.entity.TransBody;
import com.sm2cppa.utils.CertUtils;
import com.sm2cppa.utils.Transaction;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.client.protocol.response.BcosTransaction;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.utils.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.io.BufferedWriter;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


@RestController
public class ClientController {
    public String map_addr;
    @Value("${accountaddr}")
    private String account_addr;
    @Value("${caaddr}")
    private String ca_addr;
    @Value("${user1addr}")
    private String user1_addr;
    @Value("${user2addr}")
    private String user2_addr;

    private Map<String,Client> clientmap=new HashMap<>();

    @Autowired
    private Transaction transaction;

    @Autowired
    private CertUtils certUtils;

    public BufferedWriter writer;

    @PostConstruct
    public void init(){

        ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("classpath:user1-config.xml");
        // 初始化BcosSDK
        BcosSDK sdk1 =  context1.getBean(BcosSDK.class);
        // 为群组1初始化client
        clientmap.put(user1_addr,sdk1.getClient(Integer.valueOf(1)));

        ClassPathXmlApplicationContext context2 = new ClassPathXmlApplicationContext("classpath:user2-config.xml");
        BcosSDK sdk2 =  context2.getBean(BcosSDK.class);
        clientmap.put(user2_addr,sdk2.getClient(Integer.valueOf(1)));

        context1.close();
        context2.close();
    }


    @PostMapping("/getTxID")
    public ResponseBody GetTxID(@RequestBody TransBody transBody)throws Exception {
        ResponseBody response = new ResponseBody();
        String useraddr = transBody.getAddress();
        Client client=clientmap.get(useraddr);
        if(client==null){
            response.setMessage("address not found");
            return response;
        }

        String hash = transBody.getPkhash();
        byte[] pkhash=null;
        try {
            pkhash=Hex.decode(hash);
        } catch (Exception e) {
            response.setMessage("pkhash length error");
            return response;
        }

        String txid="";
        CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().getCryptoKeyPair();
        //调用合约
        MapPkToTx mapPkToTx = MapPkToTx.load(map_addr, client, cryptoKeyPair);
        long startTime = System.nanoTime();
        try {
            txid = mapPkToTx.get(pkhash);
        }catch (Exception e){
            response.setMessage("txid not found");
            return response;
        }
        if(txid.isEmpty()){
            response.setMessage("txid not found");
            return response;
        }

        long endTime =  System.nanoTime();
        double duration = (endTime - startTime) / 1_000_000.0;

        System.out.println("mapPkToTx.get: "+duration+"ms");

        response.setMessage("mapPkToTx.get: "+duration+"ms");
        response.setRuntime(duration+"ms");
        response.setTxid(txid);
        response.setStatus(1);
        return response;
    }

    @PostMapping("/getPublickey")
    public ResponseBody getPublickey(@RequestBody TransBody transBody)throws Exception{
        ResponseBody response = new ResponseBody();
        String useraddr = transBody.getAddress();
        Client client=clientmap.get(useraddr);
        if(client==null){
            response.setMessage("address not found");
            return response;
        }

        String txid= transBody.getTxid();
        String pkCert="";

        //根据txId查找交易，从交易获取证书
        long startTime3 = System.nanoTime();
        try{
            pkCert=transaction.Get_PublicKey(txid,client);
        } catch (Exception e) {
            response.setMessage("publickKey not found");
            return response;
        }

        long endTime3 =  System.nanoTime();
        double duration3 = (endTime3 - startTime3) / 1_000_000.0;

        System.out.println("Get_PublicKey time: "+duration3+" ms");

        BcosTransaction tr=client.getTransactionByHash(txid);
        response.setTransaction(tr.getResult().toString());
        response.setMessage("Get_PublicKey time: "+duration3+"ms");

        response.setPublicKey(pkCert);
        response.setRuntime(duration3+"ms");
        response.setStatus(1);
        return  response;
    }


    @PostMapping("/certverify")
    public Boolean certtest(@RequestBody CertBody certBody)throws Exception{
        String encodecert=certBody.getEncodecert();
        X509Certificate cert=certUtils.certRecover(encodecert);
        try {
            certUtils.CertVerify(cert);
        }catch (Exception e){
            return false;
        }
        return true;
    }

}
